import hashlib

Managers = {}

def GetManagers():
  ProviderInstance()
  AnalyzerInstance()
  TranscoderInstance()
  return Managers


def ProviderInstance():
  if 'Provider' not in Managers: 
    from damn.provider import Provider
    Managers['Provider'] = Provider() 
  return Managers['Provider']

def AnalyzerInstance():
  if 'Analyzer' not in Managers: 
    from damn.analyzer import Analyzer
    Managers['Analyzer'] = Analyzer() 
  return Managers['Analyzer']  

def TranscoderInstance():
  if 'Transcoder' not in Managers: 
    from damn.transcoder import Transcoder
    Managers['Transcoder'] = Transcoder() 
  return Managers['Transcoder']   
  
class FileReference():
  def __init__(self, fileName):
    self.fileName = fileName
    self._hash = None
    self.assets = []
    self.brokenReference = False
  
  @property  
  def hash(self):
    if self.brokenReference: raise Exception("Hash requested from broken reference file! %s"%(self.fileName))
    if not self._hash:
      chksum = hashlib.sha1()
      with open(self.fileName, 'rb') as fh:
        while True:
          buf = fh.read(4096)
          if not buf : break
          chksum.update(buf)
      self._hash = chksum.hexdigest()
    return self._hash
  
  @property  
  def fileNameHash(self):
    if not self.brokenReference: raise Exception("FileNameHash requested from existing file! %s"%(self.fileName))
    if not self._hash:
      self._hash = hashlib.sha1(self.fileName).hexdigest()
    return self._hash
    
  def AddAssetReference(self, anAssetReference):
    anAssetReference.file = self
    self.assets.append(anAssetReference)
  
  def GetAsset(self, subName, format=None):
    for a in self.assets:
      if a.subName == subName and (format == None or a.format == format):
        return a
    return None
        
  def serialize(self):
    return {'hash': self.hash, 'fileName': self.fileName, 'brokenReference': self.brokenReference, 
            'assets': [a.serialize() for a in self.assets]}
    
   
class AssetReference():
  def __init__(self, subName, format, file=None):
    self._id = None
    self.file = file
    if self.file:
      self.file.AddAssetReference(self)
    self.subName = subName
    self.format = format
    self.metaData = {}
    self.dependencies = []
    
  @property  
  def id(self):
    if not self._id:
      h = self.file.hash if not self.brokenReference else self.file.fileName
      self._id = hashlib.sha1(h + str(self.subName) + str(self.format)).hexdigest()
    return self._id
    
  @property  
  def brokenReference(self):
    return self.file.brokenReference
      
  def __repr__(self):
    return '(AssetReference %s - %s)'%(self.subName, self.format)
    
  def AddMetaData(self, key, value):
    self.metaData[key] = value
    
  def AddDepency(self, anAssetReference):
    self.dependencies.append(anAssetReference)
  
  def serialize(self, includeDependencies=True, includeMeta=True):
    d = {'subName': self.subName, 'format':self.format, 'brokenReference': self.brokenReference, 
         'file': self.file.hash if not self.brokenReference else self.file.fileName}
    if includeMeta:
      d['metadata'] = self.metaData
    if includeDependencies:
      d['dependencies'] = [dep.serialize(False) for dep in self.dependencies]
    return d

